<script>
import {
  setDisabledFuc,
  generatorRangeDates,
  normalizeDate,
  getNextYear,
  ONEDAYTIMESTAP,
} from './utils';
import {
  sigleDateClean,
  sigleValueInit,
  clickSingleHandle,
} from './sigleMode';
import {
  rangeClean,
  multipleValueInit,
  clickMultipleHandleOne,
} from './multipleMode';
import DateItem from './dateItem';

const today = new Date();
const weekList = ['日', '一', '二', '三', '四', '五', '六'];
const dateType = [Date, String, Number];
const valueType = [Date, String, Number, Array];
const doWeigth = ['clean', '_rangeInit', '_choiceInitType', 'valueInit'];
let changeBySelf = false;
export default {
  name: 'zaCalendar',
  components: {
    DateItem,
  },
  props: {
    prefixCls: {
      type: String,
      default: 'za-calendar',
    },
    defaultValue: {
      type: valueType,
    },
    modelValue: {
      type: valueType,
    },
    min: {
      type: dateType,
      default() {
        return today;
      },
    },
    max: {
      type: dateType,
      default() {
        return getNextYear(normalizeDate(this.$options.propsData.min) || today);
      },
    },
    multiple: {
      type: Boolean,
      default: false,
    },
    dateRender: {
      type: Function,
      default(date) {
        return <div class={`${this.prefixCls}_date-num`}>{date.getDate()}</div>;
      },
    },
    className: {
      type: String,
      default: '',
    },
    styles: {
      type: Object,
      default() {
        return {};
      },
    },
    disabledDate: {
      type: Function,
      default() {
        return false;
      },
    },
  },
  data() {
    return {
      monthList: [],
      waitingFuc: {},
    };
  },
  methods: {
    _findDateInAllDatesIndex(date) {
      return Math.ceil((date.getTime() - this.monthList[0].dates[0].date.getTime()) / ONEDAYTIMESTAP);
    },
    _findDateMonthIndex(index) {
      let monthIndex = Math.floor(index / 30);
      monthIndex = this.monthList[monthIndex - 1] && this.monthList[monthIndex - 1].maxIndex >= index ? monthIndex - 1 : monthIndex;
      if (!this.monthList[monthIndex]) { return -1; }
      return monthIndex;
    },
    _findDateInMonthList(date) {
      const index = this._findDateInAllDatesIndex(date);
      const monthIndex = this._findDateMonthIndex(index);
      if (monthIndex === -1) return null;
      const dateIndex = this.monthList[monthIndex].dates.length - (this.monthList[monthIndex].maxIndex - index);
      return {
        index,
        dateModel: this.monthList[monthIndex].dates[dateIndex],
      };
    },
    _dateEmit(value) {
      changeBySelf = true;
      this.$emit('update:modelValue', value);
      this.$emit('change', value);
    },
    _componentInit() {
      this._rangeInit();
      this._choiceInitType();
      this.valueInit();
      this.normalizeValue = null;
    },
    _rangeInit() {
      setDisabledFuc(this.disabledDate);
      this.monthList = generatorRangeDates(normalizeDate(this.min), normalizeDate(this.max));
    },
    _choiceInitType() {
      this.multiple ? this._multipleInit() : this._singleInit();
    },
    _singleInit() {
      this.clean = sigleDateClean;
      this._dateClick = clickSingleHandle;
      this.valueInit = sigleValueInit;
    },
    _multipleInit() {
      this.clean = rangeClean;
      this._dateClick = clickMultipleHandleOne;
      this.valueInit = multipleValueInit;
    },
    _pushWaitingStack(...arg) {
      arg.forEach(val => {
        this.waitingFuc[val] = true;
      });
      this._activeWaitingRun();
    },
    _activeWaitingRun() {
      this.timer && clearTimeout(this.timer);
      this.timer = setTimeout(() => {
        doWeigth.forEach(val => {
          this.waitingFuc[val] && this[val]();
        });
        this.waitingFuc = {};
      }, 10);
    },
  },
  render() {
    return (
      <div class={`${this.prefixCls} ${this.className}`} style={this.styles}>
        <ul class={`${this.prefixCls}__week`}>
          {
            weekList.map(item => <li class={`${this.prefixCls}__week-item`}>
              {item}
            </li>)
          }
        </ul>
        <ul class={`${this.prefixCls}__month`}>
          {
            this.monthList.map(month => {
              return (<li>
                <h3 class={`${this.prefixCls}__month-head`}>{month.title}</h3>
                <ul class={`${this.prefixCls}__dates`}>
                  {
                    Array.from({ length: month.dates[0].date.getDay() }, () => <li class={`${this.prefixCls}__dates-item`} />)
                  }
                  {
                    month.dates.map(dateItem => {
                      return <date-item
                        onClick={() => this._dateClick(dateItem)}
                        data={dateItem}
                        prefixCls={this.prefixCls}
                        dateRender={this.dateRender}
                      >
                      </date-item>;
                    })
                  }
                </ul>
              </li>);
            })
          }
        </ul>
      </div>
    );
  },
  created() {
    this._componentInit();
  },
  watch: {
    multiple() {
      this._pushWaitingStack('clean', '_choiceInitType');
    },
    max() {
      this._pushWaitingStack('_rangeInit', 'valueInit');
    },
    min() {
      this._pushWaitingStack('_rangeInit', 'valueInit');
    },
    defaultValue() {
      this._pushWaitingStack('valueInit');
    },
    value() {
      !changeBySelf && !this.defaultValue && this._pushWaitingStack('valueInit');
      changeBySelf = false;
    },
  },
};
</script>
